package knapsack;

import java.util.Random;

import evo.IInstance;

public class KnapsackSolution implements IInstance {
	
	private static Random _r;
	public boolean[] itemsTaken;
	public KnapsackProblem prob;
	
	public KnapsackSolution(KnapsackSolution sol)
	{
		this.prob = sol.prob;
		this.itemsTaken = new boolean[sol.itemsTaken.length];
		for (int i = 0; i < sol.itemsTaken.length; i++) {
			this.itemsTaken[i] = sol.itemsTaken[i];
		}
	}
	
	public KnapsackSolution(KnapsackProblem prob)
	{
		this.prob = prob;
		this.itemsTaken = new boolean[this.prob.weights.length];
	}
	
	public void randomize()
	{
		if (_r == null)
		{
			_r = new Random();
		}
		for (int i = 0; i < this.itemsTaken.length; i++) {
			this.itemsTaken[i] = _r.nextBoolean();
		}
		
	}

	@Override
	public double getFitness() {
		int weight = 0;
		int value = 0;
		for (int i = 0; i < this.itemsTaken.length; i++) {
			if (this.itemsTaken[i])
			{
				weight += this.prob.weights[i];
				value += this.prob.values[i];
			}
		}
		
		if (this.prob.maxWeight < weight)
		{
			return this.prob.maxWeight - weight;
		}
		return value;
	}

	@Override
	public IInstance mutate() {
		KnapsackSolution newsol = new KnapsackSolution(this);
		int i = _r.nextInt(this.itemsTaken.length);
		newsol.itemsTaken[i] = !newsol.itemsTaken[i];
		return newsol;
	}

	@Override
	public IInstance crossover(IInstance other) {
		KnapsackSolution child = new KnapsackSolution(this.prob);
		int j = _r.nextInt(this.itemsTaken.length);
		for (int i = 0; i < j; i++)
		{
			child.itemsTaken[i] = this.itemsTaken[i];
		}
		for (int i=j; i < this.itemsTaken.length; i++)
		{
			child.itemsTaken[i] = ((KnapsackSolution)other).itemsTaken[i];
		}
		return child;
	}

	@Override
	public double getMaxFitness() {
		double sum = 0;
		for (int i = 0; i < this.prob.values.length; i++) {
			sum += this.prob.values[i];
		}
		return sum;
	}

	@Override
	public int compareTo(IInstance o) {
		return (int)Math.signum(this.getFitness() - o.getFitness());
	}
	
	

}
